package com.wisdom.system.api.core.aop;

import com.wisdom.system.common.annotation.LimitTokenRequest;
import com.wisdom.system.common.exception.LogicException;
import com.wisdom.system.common.redis.RedisUtil;
import com.wisdom.system.common.util.StringUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * 接口频繁请求切面
 *
 * @author ghh
 * 2020-1-3 09:13:58
 */
@Aspect
@Component
public class LimitTokenRequestAspect {

    @Autowired
    private RedisUtil redisUtil;

    @Pointcut("@annotation(com.wisdom.system.common.annotation.LimitTokenRequest)")
    public void serviceLimit() {}

    @Around("serviceLimit()")
    public Object around(ProceedingJoinPoint joinPoint) {
        // 获取HttpRequest
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 获取请求token
        String token = request.getParameter("access_token");
        // 拦截的实体类,当前正在执行的controller
        Object target = joinPoint.getTarget();
        // 拦截的方法名称,当前正在执行的方法
        String methodName = joinPoint.getSignature().getName();
        //获取入参参数类型（String、Integer、Long等）
        Class[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getMethod().getParameterTypes();
        Method method = null;
        try {
            // 获得被拦截的方法
            method = target.getClass().getMethod(methodName, parameterTypes);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        //注解类
        LimitTokenRequest limitTokenRequest = method.getAnnotation(LimitTokenRequest.class);
        Object proceed = null;
        try {
            // proceed方法就是用于启动目标方法执行.
            proceed = joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        String value = limitTokenRequest.value();
        // 当没有定义时全部默认一个值保存到redis500ms即可消失
        if (StringUtil.isEmpty(limitTokenRequest.value())){
            value = "wisdom-system:";
        }
        if(redisUtil.exists(value + token )){
            throw LogicException.of("请求太频繁！");
        }
        redisUtil.set(value + token ,token, 500L, TimeUnit.MILLISECONDS);
        return proceed;
    }

}
